/* 
1 当前页面的数据来源 三个来源
  1 当前地位 来自于 redux
  2 热门城市 接口
  3 所有城市 接口 
2 如何处理数据格式
  1 先排序
  2 再去设想 这个数组该如何构造 才能够方便的进行循环 
3 拿到当前城市
  1 却发现 直接打开城市列表页面(直接刷新打开 不经过首页) 获取不到 当前城市
    1 原因: 把获取当前城市的代码 写在了 首页的组件中 
  2 解决
    1 有很多页面可以不经过首页就打开
    2 把获取当前地理位置的代码 写在 根组件 App.js 
      不管是哪个页面 都会经过根组件的渲染处理 
    3 修改 citySearch 里面的代码 
4 在组件挂载完毕
  1 获取到三种数据
    1 redux 当前城市
    2 接口 热门城市
    3 接口 所有城市 
  2 获取当前城市
    1 如果先打开首页 再跳转到 城市列表 那么 数据是正常
    2 如果先打开城市列表 那么 数据 是默认值 xxx 
    3 为什么  ? 
      1 在根组件发送请求 获取地理位置的同时 城市列表页面已经加载完毕
        数据还没有回来 就打印 那么 就是 默认xxx 
    4 怎么办?
      0  如果是使用原生redux的话 订阅 对数据判断   
      1  App组件中做条件渲染 可以的 !! 
5 长列表的渲染模式  重要!! 
  1 假如后台有10万条数据  前端如何渲染 性能才比较好 
    1 整页加载
      1 浪费性能 前端和后端都浪费  
    2 分页加载  
      1 第一次加载的时候 拿 50条回来
        1 页面就拿50条数组 渲染
        ....
        每一次去新的加载的时候 都拿50条
        页面马上跟渲染 新的50条
        ....
        list 的数组长度 = 10万
        页面中的dom元素的数量 也是 10万 
    3 可视区域渲染
      1 最终的效果
        list 数组的长度 = 10万
        页面中的dom元素的数量  只有 50个 (永远都是用户想要看到的50条数据)
        1-50 
        51-100
        101-150
6 字母列表
  1 构造数据 将它循环显示出来 
  2 点击右侧字母 
    1 激活选中 
    2 页面滑动
      1 挺复杂(不复杂  按照 工资6K 一点都不复杂!!!  ) (不知道这个功能 肯定在插件中有 ) 去找文档即可   
  3 滑动页面 右侧字母切换
    1 查阅文档 
7 点击返回按钮 返回上一页 
8 点击城市名称 
  1 修改 当前的地理位置 redux 同步操作
  2 返回上一页 
 
 */
import React, { Component } from 'react';

import { connect } from "react-redux";

import { request } from "../../utils/request";
import { NavBar, Icon } from 'antd-mobile';
import indexCss from "./index.module.scss";
import { List } from "react-virtualized";
import { changeCityName } from "../../store/actionCreator";


console.log("城市列表");

class Index extends Component {
  state = {
    // 主要数组
    list: [],
    // 字母数组
    letterList: [],
    // 字母 选中的索引
    currentIndex: 0
  }
  constructor() {
    super();
    this.listRef = React.createRef();
  }
  async componentDidMount() {
    // 1 获取redux中的城市名称获取到 
    const { cityName } = this.props;
    // 2 获取热门城市   3s

    // 4 数据合并和处理  一共花费 8s
    //  数据全部都回来  才 开始处理   Promise.all 
    const res = await Promise.all([request.get("/area/hot"), request.get("/area/city?level=1")]);
    const hotCitys = res[0].body;
    // 对所有城市进行排序
    const allCitys = res[1].body.sort((a, b) => a.short < b.short ? -1 : 1);

    // 5 在这里才开始做合并的业务 
    const uniList = [];

    // 5.5 声明字母数组
    const letterList = ["#", "热"];

    // 6 添加 当前城市
    uniList.push({
      title: "当前定位",
      list: [{ label: cityName }]
    })
    // 7 添加 热门城市
    uniList.push({
      title: "热门城市",
      list: hotCitys
    });

    // 8 添加所有城市的数据
    allCitys.forEach(allcity => {
      // allcity = 
      // 判断 安庆这个对象是 存在于 uniList
      const firstLetter = allcity.short[0].toUpperCase();// A 
      const index = uniList.findIndex(unicity => {
        // unicity 
        // aq[0]=a
        if (firstLetter === unicity.title) {
          return true;
        } else { return false }
      });
      if (index === -1) {
        //  不存在
        uniList.push({
          title: firstLetter,
          list: [allcity]
        })
        // console.log(firstLetter);
        letterList.push(firstLetter);

      } else {
        // 存在 拼接数组list
        uniList[index].list.push(allcity);
      }
    })
    this.setState({ list: uniList, letterList });


  }

  // 城市列表的每一项 渲染函数
  rowRenderer = ({
    key, // Unique key within array of rows
    index, // Index of row within collection
    isScrolling, // The List is currently being scrolled
    isVisible, // This row is visible within the List (eg it is not an overscanned row)
    style, // Style object to be applied to row (to position it)
  }) => {
    const { list } = this.state;
    const item = list[index];
    return (
      <div key={key} style={style}>
        <div className={indexCss.city_group_title}>{item.title}</div>
        <div className={indexCss.city_group_list}>
          {
            item.list.map(v => <div key={v.label} className={indexCss.city_item}
              onClick={this.onCityClick.bind(this, v.label)}
            >
              {v.label}
            </div>)
          }
        </div>
      </div>
    );
  }
  // 动态计算 list中每一大行的高度 (当前城市,热门城市 一行)
  rowHeight = ({ index }) => {
    const { list } = this.state;
    // 标题和 城市 高都是 40px
    // 1vw 等于 100分之一屏幕的宽度 
    // 1vw =   window.outerWidth*0.01

    return (list[index].list.length + 1) * 40 * 0.3125 * window.outerWidth * 0.01
  }

  // 点击右侧字母列表
  onLetterClick = (currentIndex) => {
    // console.log(currentIndex);
    this.setState({ currentIndex });
    // console.log(this.listRef);
    // 调用list组件的方法 让他 根据一个索引进行 滚动
    this.listRef.scrollToRow(currentIndex);
  }

  // 页面滚动 渲染完毕 会触发的回调函数
  onRowsRendered = ({ overscanStartIndex, overscanStopIndex, startIndex, stopIndex }) => {
    // console.log(" 现在就被显示的 行的索引 顶部  startIndex",startIndex);
    // console.log("现在就被显示的 行的索引,列表的底部 stopIndex",stopIndex);
    this.setState({ currentIndex: startIndex })
  }

  // 点击城市名称
  onCityClick = (cityName) => {
    // 派发到管理员
    this.props.changeCurrentCity(cityName);
    // 执行跳回上一页
    this.props.history.goBack();
  }
  render() {
    const { list, letterList, currentIndex } = this.state;
    return (
      <div className={indexCss.city_list} >
        <NavBar
          mode="light"
          icon={<Icon type="left" />}
          onLeftClick={() => this.props.history.goBack()}
        >城市选择 {this.props.cityName} </NavBar>
        <div className={indexCss.city_list_view} >
          <List
            ref={ref => this.listRef = ref}
            rowCount={list.length}
            width={window.outerWidth}
            height={window.outerHeight - 45}
            rowHeight={this.rowHeight}
            rowRenderer={this.rowRenderer}
            scrollToAlignment="start"
            onRowsRendered={this.onRowsRendered}
          />

          {/* 字母列表 */}
          <div className={indexCss.letter_list}>
            {
              letterList.map((v, i) => <div key={v}
                className={[indexCss.letter_item, i === currentIndex ? indexCss.active : ""].join(" ")}
                onClick={this.onLetterClick.bind(this, i)}
              ><span>{v}</span></div>)
            }
          </div>
        </div>
      </div>
    );
  }
}


const mapStateToProps = (state) => ({
  cityName: state.mapReducer.cityName
})

const mapDispatchToProps = (dispatch) => ({
  changeCurrentCity(cityName) {
    // console.log("获取到被点击的城市名称 发送通知给管理员");
    // console.log(cityName);
    dispatch(changeCityName(cityName));
    // 执行返回上一页
    // this.props.ge
  }
}
)



export default connect(mapStateToProps, mapDispatchToProps)(Index);